/* pongian.c */

#include "pongian.h"

SDL_Surface *screen;
TTF_Font * plain_font;
struct environment pongian;
SDL_Color normal_color;
SDL_Color select_color;



void quitPongian(int parameter)
{
	if (parameter == 1)
	{
		// cleanup
		SDL_FreeSurface(screen);
	}
	exit(parameter);
}

void game_draw_brick(SDL_Surface * target, unsigned int xpos, unsigned int ypos)
{
	rectangleRGBA(target, xpos, ypos, xpos+BRICK_LENGTH, ypos+BRICK_HEIGHT, 255, 255, 255, 255);
//	printf("game_draw_brick(): xpos %d, ypos %d, xpos2 %d, ypos2 %d\n", xpos, ypos, xpos+BRICK_LENGTH, ypos+BRICK_HEIGHT);
}

void game_draw_bricks(SDL_Surface * target, struct plf_file * level_data)
{
	unsigned int xcounter = 0, ycounter = 0;
	while(ycounter < (4*BRICK_HEIGHT)) {
		game_draw_brick(target, xcounter, ycounter);
		xcounter = xcounter + BRICK_LENGTH;
		if (xcounter >= 800) {
			ycounter = ycounter + BRICK_HEIGHT;
			xcounter = 0;
		}
//		printf("xcounter %d, ycounter %d\n", xcounter, ycounter);
	}
}
/*
void game_draw_paddles(SDL_Surface * target, struct paddle * p1, struct paddle * p2)
{
	rectangleRGBA(target, p1->pos.x, p1->pos.y, p1->pos.x+p1->pos.w, pongian.y-1, p1->color.r, p1->color.g, p1->color.b, p1->alpha);
	rectangleRGBA(target, p2->pos.x, p2->pos.y, p2->pos.x+p2->pos.w, p2->pos.h, p2->color.r, p2->color.g, p2->color.b, p2->alpha);
}
*/

void game_draw_paddle(SDL_Surface * target, struct paddle * p)
{
	rectangleRGBA(target, p->pos.x, p->pos.y, p->pos.x+p->pos.w, p->pos.y+PADDLE_HEIGHT, p->color.r, p->color.g, p->color.b, p->alpha);
}

void game_draw_ball(SDL_Surface * target, struct pball * ball)
{
	rectangleRGBA(target, ball->pos.x, ball->pos.y, ball->pos.x + ball->pos.w, ball->pos.y + ball->pos.h, ball->color.r, ball->color.g, ball->color.b, ball->alpha);
}

void game_draw_background(SDL_Surface * target)
{
	SDL_FillRect(target, NULL, SDL_MapRGB(target->format, 0, 0, 0));
}

void game_draw_score_screen(char * player1_name, unsigned int player1_score, char * player2_name, unsigned int player2_score, unsigned int who_won)
{
	char temp_string[255];
	if (who_won == 1)
	{
		sprintf(temp_string, "%s scores!", player1_name);
	} else if (who_won == 2)
	{
		sprintf(temp_string, "%s scores!", player2_name);
	}
	pmenu_text_center(temp_string, plain_font, select_color, 50, screen);
	sprintf(temp_string, "%s: %2d", player1_name, player1_score);
	pmenu_text_center(temp_string, plain_font, normal_color, 150, screen);
	sprintf(temp_string, "%s: %2d", player2_name, player2_score);
	pmenu_text_center(temp_string, plain_font, normal_color, 200, screen);
	pmenu_text_center("press any key", plain_font, select_color, 250, screen);
}

void game_draw_end_screen(char * player_name)
{
	char temp_string[255];
	sprintf(temp_string, "%s won the game!", player_name);
	pmenu_text_center(temp_string, plain_font, select_color, 50, screen);
}

unsigned int game(unsigned int game_mode, unsigned int players_turn, char * level_file)
{
	unsigned int quit = 0;
	unsigned int movement_mode = PONGIAN_MOVEMENT_MODE;

	struct paddle player1;
	struct paddle player2;
	struct pball ball;

	FILE * file_handle;
	struct plf_file level_file_data;

	player1.pos.w = PADDLE_LENGTH;
	player2.pos.w = PADDLE_LENGTH;
	player1.pos.h = PADDLE_HEIGHT;
	player2.pos.h = PADDLE_HEIGHT;
	player1.pos.x = pongian.x / 2 - player1.pos.w / 2;
	player1.pos.y = pongian.y - player1.pos.h-1;
	player2.pos.x = pongian.x / 2 - player2.pos.w / 2;
	player2.pos.y = 0;
	player1.wanted_speed = 0;
	player2.wanted_speed = 0;
	player1.current_speed = 0;
	player2.current_speed = 0;

	player1.color.r = 0;
	player1.color.g = 255;
	player1.color.b = 0;
	player1.alpha = 255;

	player2.color.r = 0;
	player2.color.g = 0;
	player2.color.b = 255;
	player2.alpha = 255;

	ball.pos.x = 0;
	ball.pos.y = 0;
	ball.pos.w = 15;
	ball.pos.h = 15;
	ball.color.r = 255;
	ball.color.g = 0;
	ball.color.b = 0;
	ball.alpha = 255;
	ball.speed_x = 0;
	ball.speed_y = 0;

	float paddle_speed = PADDLE_SPEED;
	if (movement_mode == 1) paddle_speed = PADDLE_SPEED_2;
	float paddle_speed_accel = PADDLE_SPEED_ACCEL;
	float ball_speed = BALL_SPEED;

	unsigned int player1_left_is_pressed = 0;
	unsigned int player1_right_is_pressed = 0;
	unsigned int player2_left_is_pressed = 0;
	unsigned int player2_right_is_pressed = 0;

	SDL_Event event;

	if (game_mode == 3)
	{
		file_handle = fopen(level_file, "r");
		fread(&level_file_data, sizeof(level_file_data), 1, file_handle);
		fclose(file_handle);
	}

	// initial screen
	game_draw_background(screen);
//	game_draw_paddles(screen, &player1, &player2);
	game_draw_paddle(screen, &player1);
	if (game_mode != 3) game_draw_paddle(screen, &player2);
	game_draw_ball(screen, &ball);
	if (game_mode == 3) game_draw_bricks(screen, &level_file_data);

	SDL_Flip(screen);	
	while (quit == 0)
	{
		if (SDL_PollEvent(&event))
		{
			if (event.type == SDL_KEYDOWN)
			{
				switch(event.key.keysym.sym)
				{
					case SDLK_ESCAPE:
						quit = 3;
					break;
					
					case SDLK_a:
						if (game_mode == 0) player2_left_is_pressed = 1;
					break;
					
					case SDLK_d:
						if (game_mode == 0) player2_right_is_pressed = 1;
					break;
					
					case SDLK_w:
						if ((players_turn == 2) && (game_mode == 0))
						{
							ball.speed_x = ball_speed;
							ball.speed_y = ball_speed;
							players_turn = 0;
						}
					break;
					
					case SDLK_LEFT:
						player1_left_is_pressed = 1;
					break;
					
					case SDLK_RIGHT:
						player1_right_is_pressed = 1;
					break;
					
					case SDLK_UP:
						if (players_turn == 1)
						{
							ball.speed_x = ball_speed;
							ball.speed_y = ball_speed * -1;
							players_turn = 0;
						}
					break;
				}
			}
			if (event.type == SDL_KEYUP)
			{
				switch(event.key.keysym.sym)
				{
					case SDLK_a:
						player2_left_is_pressed = 0;
					break;
					case SDLK_d:
						player2_right_is_pressed = 0;
					break;
					case SDLK_LEFT:
						player1_left_is_pressed = 0;
					break;
					case SDLK_RIGHT:
						player1_right_is_pressed = 0;
					break;
				}
			}
		}
		switch(players_turn)
		{
			case 1:
				ball.pos.x = player1.pos.x + player1.pos.w / 2 - ball.pos.w / 2;
				ball.pos.y = player1.pos.y - ball.pos.h;
			break;
			case 2:
				ball.pos.x = player2.pos.x + player2.pos.w / 2 - ball.pos.w / 2;
				ball.pos.y = player2.pos.y + player2.pos.h;
			break;
			default:
				ball.pos.x += ball.speed_x;
				ball.pos.y += ball.speed_y;
			break;
		}
		if (game_mode == 1)
		{
			if (players_turn == 2)
			{

				ball.speed_x = ball_speed;
				ball.speed_y = ball_speed * -1;
				printf("x %d y %d sx %f sy %f\n", ball.pos.x, ball.pos.y, ball.speed_x, ball.speed_y);
				players_turn = 0;
			} else
			{
				if (ball.pos.x > (player2.pos.x + player2.pos.w))
				{
					player2_right_is_pressed = 1;
					player2_left_is_pressed = 0;
				}
				if (ball.pos.x < (player2.pos.x))
				{
					player2_right_is_pressed = 0;
					player2_left_is_pressed = 1;
				}
			}
		}
		if (movement_mode == 0)
		{
			if (player1_left_is_pressed == 1) player1.wanted_speed -= paddle_speed;
			if (player1_right_is_pressed == 1) player1.wanted_speed += paddle_speed;
			if (player2_left_is_pressed == 1) player2.wanted_speed -= paddle_speed;
			if (player2_right_is_pressed == 1) player2.wanted_speed += paddle_speed;

			if (player1.current_speed < player1.wanted_speed) player1.current_speed += paddle_speed_accel;
			if (player1.current_speed > player1.wanted_speed) player1.current_speed -= paddle_speed_accel;		
			if (player2.current_speed < player2.wanted_speed) player2.current_speed += paddle_speed_accel;
			if (player2.current_speed > player2.wanted_speed) player2.current_speed -= paddle_speed_accel;

			player1.pos.x += player1.current_speed;
			player2.pos.x += player2.current_speed;
		} else
		{
			if (player1_left_is_pressed == 1) player1.pos.x -= paddle_speed;
			if (player1_right_is_pressed == 1) player1.pos.x += paddle_speed;
			if (player2_left_is_pressed == 1) player2.pos.x -= paddle_speed;
			if (player2_right_is_pressed == 1) player2.pos.x += paddle_speed;
		}
		if (player1.pos.x < 0)
		{
			player1.pos.x = 0;
			player1.current_speed = 0;
			player1.wanted_speed = 0;
		}
		if (player2.pos.x < 0)
		{
			player2.pos.x = 0;
			player2.current_speed = 0;
			player2.wanted_speed = 0;
		}
		if ((player1.pos.x + player1.pos.w) > pongian.x)
		{
			player1.pos.x = pongian.x - player1.pos.w - 1;
			player1.current_speed = 0;
			player1.wanted_speed = 0;
		}
		if ((player2.pos.x + player2.pos.w) > pongian.x)
		{
			player2.pos.x = pongian.x - player2.pos.w - 1;
			player2.current_speed = 0;
			player2.wanted_speed = 0;
		}
		if (players_turn == 0)
		{
			if (ball.pos.x + ball.pos.w > pongian.x)
			{
				ball.pos.x = pongian.x - ball.pos.w;
				ball.speed_x *= -1;
			}
			if (ball.pos.x < 0)
			{
				ball.pos.x = 0;
				ball.speed_x *= -1;
			}
			if (((ball.pos.y > (player2.pos.h - 1)) && (ball.pos.y < (player2.pos.h + 1))) && (ball.pos.x < (player2.pos.x + player2.pos.w)) && (ball.pos.x > (player2.pos.x - ball.pos.w)))
			{
				ball.pos.y = player2.pos.h;
				ball.speed_y *= -1;
				ball.speed_x += player2.current_speed;
				printf("bsx %f p2cs %f\n", ball.speed_x, player2.current_speed);
			}
			if ((((ball.pos.y + ball.pos.h) > (player1.pos.y - 1)) && ((ball.pos.y + ball.pos.h) < (player1.pos.y + 1))) && (ball.pos.x < (player1.pos.x + player1.pos.w)) && (ball.pos.x > (player1.pos.x - ball.pos.w)))
			{
				ball.pos.y = player1.pos.y - ball.pos.h;
				ball.speed_y *= -1;
				ball.speed_x += player1.current_speed;
				printf("bsx %f p1cs %f\n", ball.speed_x, player1.current_speed);
			}
			if (game_mode == 0)
			{
				if (ball.pos.y < (0 - ball.pos.h))
				{
					quit = 1;
				}
			} else if (game_mode == 3) {
				ball.speed_y *= -1;
			}
			if (ball.pos.y > pongian.y)
			{
				quit = 2;
			}
		
		}
		game_draw_background(screen);
		if (game_mode == 3) game_draw_bricks(screen, &level_file_data);
		game_draw_paddle(screen, &player1);
		if (game_mode != 3) game_draw_paddle(screen, &player2);
		game_draw_ball(screen, &ball);
		SDL_Flip(screen);
		SDL_Delay(TimeLeft());
	}
	return quit;
}


void gameLoop(unsigned int game_mode)
{
	unsigned int player1_wins = 0;
	unsigned int player2_wins = 0;
	unsigned int quit = 0;
	unsigned int max_wins = 5;
	unsigned int next_player = 1;
	unsigned int round = 0;
	if ((game_mode == 0) || (game_mode == 1))
	{
		while((player1_wins < max_wins) && (player2_wins < max_wins) && (quit == 0))
		{
			switch(game(game_mode, next_player, NULL))
			{
				case 1:
					player1_wins++;
					printf("player 1 won\n");
					game_draw_score_screen("Player 1", player1_wins, "Player 2", player2_wins, 1);
					SDL_Flip(screen);
					pmenu_wait_for_any_key();
					next_player = 2;
				break;
				case 2:
					player2_wins++;
					printf("player 2 won\n");
					game_draw_score_screen("Player 1", player1_wins, "Player 2", player2_wins, 2);
					SDL_Flip(screen);
					pmenu_wait_for_any_key();
					next_player = 1;
				break;
				default:
					quit = 1;
					printf("game quit\n");
				break;
			}
		}
		if (player1_wins >= max_wins)
		{
			SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));
			game_draw_end_screen("Player 1");
			SDL_Flip(screen);
			pmenu_wait_for_any_key();
		}
		if (player2_wins >= max_wins)
		{
			SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));
			game_draw_end_screen("Player 1");
			SDL_Flip(screen);
			pmenu_wait_for_any_key();
		}
	}
/*	if (game_mode == 1)
	{
		while ((round < 3) && (quit == 0))
		{
			while((player1_wins < max_wins) && (player2_wins < max_wins) && (quit == 0))
			{
				switch(game(game_mode, next_player))
				{
					case 1:
						player1_wins++;
						printf("player 1 won\n");
						next_player = 2;
					break;
					case 2:
						player2_wins++;
						printf("player 2 won\n");
						next_player = 1;
					break;
					default:
						quit = 1;
						printf("game quit\n");
					break;
				}
			}
		}
	}*/
}


void arcadeGame(void)
{
	unsigned char level = 0;
	unsigned char quit = 0;
	while ((level < 2) && (quit == 0))
	{
		switch(level)
		{
			case 0:
				game(3, 1, "level01.plf");
			break;
			case 1:
				gameLoop(1);
			break;
		}
		level++;
	}
	
}

void aboutPongian(void)
{
	SDL_Surface *temp_surface;
	unsigned int quit = 0;
	SDL_Event event;
	SDL_Rect text_dest;
	SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));
	text_dest.x = 150;
	text_dest.y = 100;
	temp_surface = TTF_RenderText_Blended(plain_font, "about pongian", select_color);
	SDL_BlitSurface(temp_surface, NULL, screen, &text_dest);
	SDL_FreeSurface(temp_surface);
	text_dest.y = 130;
	temp_surface = TTF_RenderText_Blended(plain_font, "pongian united version 1", normal_color);
	SDL_BlitSurface(temp_surface, NULL, screen, &text_dest);
	SDL_FreeSurface(temp_surface);
	text_dest.y = 155;
	temp_surface = TTF_RenderText_Blended(plain_font, "written by s.zidar, 2008", normal_color);
	SDL_BlitSurface(temp_surface, NULL, screen, &text_dest);
	SDL_FreeSurface(temp_surface);
	SDL_Flip(screen);
	while(!quit)
	{
		if (SDL_PollEvent(&event))
		{
			if (event.type == SDL_KEYDOWN)
			{
				switch(event.key.keysym.sym)
				{
					case SDLK_RETURN:
					case SDLK_ESCAPE:
					case SDLK_SPACE:
						quit = 1;
					break;
				}
			}
		}
		SDL_Delay(TimeLeft());
	}
}

int alternative_menue(void)
{
//	struct pmenu_root main_menue;
	int selection = 0;
	unsigned int quit = 0;
	SDL_Event event;
	SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));
	pmenu_text_center("arcade game", plain_font, select_color, 120, screen);
	pmenu_text_center("two-player battle game", plain_font, normal_color, 150, screen);
	pmenu_text_center("about", plain_font, normal_color, 180, screen);
	pmenu_text_center("quit", plain_font, normal_color, 210, screen);
	SDL_Flip(screen);
	while(!quit)
	{
		if (SDL_PollEvent(&event))
		{
			if (event.type == SDL_KEYDOWN)
			{
				switch(event.key.keysym.sym)
				{
					case SDLK_UP:
						selection--;
						if (selection < 0) selection = 3;
					break;
					
					case SDLK_DOWN:
						selection++;
						if (selection > 3) selection = 0;
					break;

					case SDLK_ESCAPE:
						quit = 1;
					break;
					
					case SDLK_RETURN:
						if (selection == 0) arcadeGame();
						if (selection == 1) gameLoop(0);
						if (selection == 2) aboutPongian();
						if (selection == 3) quit = 1;
					break;
				}
				SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));
				if (selection == 0) {
					pmenu_text_center("arcade game", plain_font, select_color, 120, screen);
				} else {
					pmenu_text_center("arcade game", plain_font, normal_color, 120, screen);
				}
				if (selection == 1) {
					pmenu_text_center("two-player battle game", plain_font, select_color, 150, screen);
				} else {
					pmenu_text_center("two-player battle game", plain_font, normal_color, 150, screen);
				}
				if (selection == 2) {
					pmenu_text_center("about", plain_font, select_color, 180, screen);
				} else {
					pmenu_text_center("about", plain_font, normal_color, 180, screen);
				}
				if (selection == 3) {
					pmenu_text_center("quit", plain_font, select_color, 210, screen);
				} else {
					pmenu_text_center("quit", plain_font, normal_color, 210, screen);
				}
				SDL_Flip(screen);
			}
		}
		SDL_Delay(TimeLeft());
	}
	return selection;
}


int main(int argnum, char *argstr[])
{
	if (argnum > 1)
	{
		if (strcmp(argstr[1], "-gen") == 0)
		{
			printf("generating level...");
			if (plf_generate_level())
			{
				printf("ok\n");
			} else
			{
				printf("failed\n");
			}
			exit(1);
		}
	}
	normal_color.r = 255;
	normal_color.g = 255;
	normal_color.b = 255;
	select_color.r = 70;
	select_color.g = 70;
	select_color.b = 255;
	pongian.x = 640;
	pongian.y = 480;
	pongian.bpp = 16;
	pongian.flags = SDL_HWSURFACE;
	if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) 
	{
		printf("there was a problem initialising sdl.\n");
		quitPongian(-1);
	}
	atexit(SDL_Quit);
	screen = SDL_SetVideoMode(pongian.x, pongian.y, pongian.bpp, pongian.flags);
	if (screen == NULL) 
	{
		printf("there was a problem creating the sdl surface.\n");
    	quitPongian(-1);
	}
	if (TTF_Init() == -1)
	{
		printf("there was a problem initialising sdl_ttf.\n");
		quitPongian(-2);
	}
	plain_font = TTF_OpenFont("data/fonts/VeraMono.ttf", 24);
	if (!plain_font)
	{
		printf("there was a problem loading the font.\n");
		quitPongian(-2);
	}
	SDL_WM_SetCaption("pongian light", "pongian light");
	alternative_menue();
	quitPongian(1);
}

